namespace Yaaf.Wp7.AdvancedExplorer
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.IO.IsolatedStorage;
    using System.Linq;
    using System.Windows;

    using Microsoft.Phone.Shell;

    using Yaaf.Wp7.AdvancedExplorer.Resources;
    using Yaaf.Wp7.AdvancedExplorer.ViewModels;
    using Yaaf.WP7.NativeAccess.IO;
    using Yaaf.WP7.NativeAccess.Provision;
    using Yaaf.WP7.NativeAccess.Registry;

    public class UriView : INotifyPropertyChanged
    {
        private UriBuilder builder;
        public UriView(string uri)
        {
            builder = new UriBuilder(uri);
        }

        public string CompleteUri
        {
            get
            {
                return builder.ToString();
            }

            set
            {
                builder = new UriBuilder(value);
                InvokePropertyChanged("Scheme");
                InvokePropertyChanged("Port");
                InvokePropertyChanged("Path");
                InvokePropertyChanged("Host");
            }
        }

        public string Scheme
        {
            get
            {
                return builder.Scheme;
            }

            set
            {
                builder.Scheme = value;
                this.InvokePropertyChanged("Scheme");
                this.InvokePropertyChanged("CompleteUri");
            }
        }

        public string Port
        {
            get
            {
                return builder.Port.ToString();
            }

            set
            {
                int port;
                if (int.TryParse(value, out port))
                {
                    builder.Port = port;
                    this.InvokePropertyChanged("Port");
                    this.InvokePropertyChanged("CompleteUri");
                }
                else
                {
                    System.Windows.MessageBox.Show("Invalid Port!");
                }
            }
        }

        public string Path
        {
            get
            {
                return builder.Path;
            }

            set
            {
                builder.Path = value;
                this.InvokePropertyChanged("Path");
                this.InvokePropertyChanged("CompleteUri");
                
            }
        }

        public string Host
        {
            get
            {
                return builder.Host;
            }

            set
            {
                builder.Host = value;
                this.InvokePropertyChanged("Host");
                this.InvokePropertyChanged("CompleteUri");

            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void InvokePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public override string ToString()
        {
            return CompleteUri;
        }
    }

    public class Settings : IPivotView
    {
        private const string MaxUnsignedAppValue = "HKLM\\Software\\Microsoft\\DeviceReg\\Install\\MaxUnsignedApp";

        private static Settings current;
        public static Settings Current
        {
            get
            {
                if (current == null)
                {
                    current = new Settings();
                    current.Load();
                }
                return current;
            }
        }

        public UriView RemoteServer { get; set; }
        
        public string MaxUnsignedApp { get; set; }

        public bool ExitQuestion { get; set; }

        public bool RunUnderLock { get; set; }

        public bool UseLimitedFileAccess { get; set; }


        private const string BlueModernStyle = "bluemodern";
        private static string[] availableStyles = new string[] { BlueModernStyle, "greenold", "normal" };

        public IEnumerable<string> AvailableStyles
        {
            get
            {
                return availableStyles;
            }
            set
            {
                availableStyles = value.ToArray();
            }
        }

        public string SelectedStyle { get; set; }

        public Settings()
        {
            // Default values
            RemoteServer = new UriView("http://" + "127.0.0.1" + ":" + "8001" + "/FileExchangeService/");
            SelectedStyle = BlueModernStyle;
            UseLimitedFileAccess = false;
            MaxUnsignedApp = AppResources.SaveMaxAppNotSet;
            ExitQuestion = false;
            RunUnderLock = false;
        }


        public void Load()
        {
            var i = System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings;

            if (i.Contains("RemoteServer"))
            {
                RemoteServer = new UriView((string)i["RemoteServer"]);
            }

            if (i.Contains("SelectedStyle"))
            {
                SelectedStyle = (string)i["SelectedStyle"];
            }
            
            if (i.Contains("UseLimitedFileAccess"))
            {
                UseLimitedFileAccess = (bool)i["UseLimitedFileAccess"];
            }
            
            FileSystemAccess.UseLimitedAccess = UseLimitedFileAccess;
            
            #region MaxUnsignedApp
            bool maxUnsignedAppSet = false;
            if (i.Contains("MaxUnsignedApp"))
            {
                MaxUnsignedApp = (int)i["MaxUnsignedApp"] + AppResources.SaveMaxAppStartUp;
                maxUnsignedAppSet = true;
            }
            else
            {
                int? value = null; 
                if (Registry.IsAvailable)
                {
                    try
                    {
                        value = (int)Registry.GetValue(MaxUnsignedAppValue);
                    }
                    catch (UnauthorizedAccessException)
                    {
                    }
                }

                if (value.HasValue)
                {
                    MaxUnsignedApp = value.Value +  AppResources.SaveMaxAppReadRegistry;
                }
            }

            if (current == this && maxUnsignedAppSet)
            {
                if (Registry.IsAvailable)
                {
                    try
                    {
                        Registry.SetValue(MaxUnsignedAppValue, (int)i["MaxUnsignedApp"], RegistryValueKind.DWord);
                    }
                    catch (Exception e)
                    {
                        this.MaxUnsignedApp = (int)i["MaxUnsignedApp"] + AppResources.SaveMaxAppError;
                        Console.WriteLine(AppResources.Error2 + e);
                    }
                }
                else
                {
                    MaxUnsignedApp = (int)i["MaxUnsignedApp"] + AppResources.SaveMaxAppRegistryNotAvailable;
                }
            }
            #endregion

            if (i.Contains("ExitQuestion"))
            {
                ExitQuestion = (bool)i["ExitQuestion"];
            }

            if (i.Contains("RunUnderLock"))
            {
                RunUnderLock = (bool)i["RunUnderLock"];
            }

            SetRunUnderLock(RunUnderLock);
        }

        public void Save()
        {
            var i = System.IO.IsolatedStorage.IsolatedStorageSettings.ApplicationSettings;
            i["RemoteServer"] = RemoteServer.ToString();
            int max;
            if (int.TryParse(MaxUnsignedApp, out max))
            {
                i["MaxUnsignedApp"] = max;
            }
            i["ExitQuestion"] = ExitQuestion;
            i["SelectedStyle"] = SelectedStyle;
            i["RunUnderLock"] = RunUnderLock;
        }

        public string Header
        {
            get
            {
                return "settings";
            }
        }

        public Settings Copy()
        {
            var s = new Settings();
            s.RemoteServer = this.RemoteServer;
            s.MaxUnsignedApp = this.MaxUnsignedApp;
            s.ExitQuestion = this.ExitQuestion;
            s.UseLimitedFileAccess = this.UseLimitedFileAccess;
            s.SelectedStyle = this.SelectedStyle;
            s.RunUnderLock = this.RunUnderLock;
            return s;
        }

        public void SetAll(Settings settings)
        {
            var s = this;
            s.RemoteServer = settings.RemoteServer;
            int max;
            if (int.TryParse(settings.MaxUnsignedApp, out max))
            {
                s.MaxUnsignedApp = max.ToString();
            }
            else
            {
                max = -1;
            }
            s.MaxUnsignedApp = settings.MaxUnsignedApp;
            s.ExitQuestion = settings.ExitQuestion;
            s.SelectedStyle = settings.SelectedStyle;
            s.RunUnderLock = settings.RunUnderLock;

            if (this == Settings.Current)
            {
                SetRunUnderLock(settings.RunUnderLock);

                FileSystemAccess.UseLimitedAccess = settings.UseLimitedFileAccess;

                if (max != -1)
                {
                    try
                    {
                        Registry.SetValue("HKLM\\Software\\Microsoft\\DeviceReg\\Install\\MaxUnsignedApp", max, RegistryValueKind.DWord);
                    }
                    catch (Exception ex)
                    {
                        max = -1;
                        MessageBox.Show(string.Format(AppResources.ErrorSettingRegistry, ex));
                    }
                }

                MessageBox.Show(string.Format(AppResources.SettingsSaved, (max != -1)));
            }

        }

        private static void SetRunUnderLock(bool runUnderLock)
        {
            var newSetting = runUnderLock
                                 ? IdleDetectionMode.Disabled
                                 : IdleDetectionMode.Enabled;
            var oldSetting = PhoneApplicationService.Current.ApplicationIdleDetectionMode;
            if (oldSetting != newSetting)
            {
                try
                {
                    PhoneApplicationService.Current.ApplicationIdleDetectionMode = newSetting;
                }
                catch (InvalidOperationException)
                {
                    MessageBox.Show(AppResources.ErrorSettingRunUnderLock);
                }
            }
        }
    }
}